home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / batchut / rbsetnv1.zip / EVAL.C < prev    next >
Text File  |  1991-01-03  |  6KB  |  177 lines

  1. /*
  2.  * eval.c - evaluate a command, with command substitution, environment variable
  3.  *            substitution, and wildcard expansion
  4.  *
  5.  * Author:        R. Brittain                        4/11/90
  6.  *
  7.  *    Popen() is adapted from code obtained from simtel20
  8.  *  Recommended wildcard expansion code to use with this is wildargv.c by
  9.  *     Frank Whaley and placed in the public domain
  10.  *
  11.  * Syntax:
  12.  *        eval command argument argument .....
  13.  *
  14.  * Description:
  15.  *  The arguments to eval are first wildcard expanded (wildcards expanded into
  16.  *  alphabetically sorted lists as in unix) and then interatively scanned
  17.  *  for variable substitutions (%val or $val if you prefer) and command
  18.  *  substitutions (commands enclosed in `....`)
  19.  *  After the expansion, the first word is taken to be a command, which
  20.  *  is then executed , with the rest of the expansion as arguments.
  21.  *
  22.  *  Command substitutions are usually performed by loading a shell (%SHELL or
  23.  *  %COMSPEC) to run the the command.  If the first character of the
  24.  *  command is '@' the command is exec'ed directly (much faster than calling
  25.  *  system, but only works with .exe and .com files).  Loading a shell allows
  26.  *  internal commands, batch files, shell aliases and pipelines.
  27.  *
  28.  *  The magic characters %,`, and @ are set below by #defines
  29.  *
  30.  *                    This code placed in the public domain
  31.  *
  32.  *  If your shell cannot handle a switch character other than /, #define SWITCH
  33.  *  By default, the subshells will be called as %COMSPEC ?c command - where ?
  34.  *  is the current switchar.   Defining SWITCH forces use of /
  35.  *
  36.  *  Revision history
  37.  *    1.0     - first posted to net Dec 90                            RB
  38.  *    1.01    - fixed argument parsing so `.....` can span multiple arguments
  39.  *              without needing to be double quoted            Jan 91    RB
  40.  *
  41.  */
  42. #include <string.h>
  43. #include <ctype.h>
  44. #include <dos.h>
  45. #include <stdlib.h>
  46. #include <stdio.h>
  47. #include <process.h>
  48.  
  49. #include "comsub.h"
  50.  
  51. #define MEMCHECK(x)        if ((x) == NULL) fatal("Out of memory",1)
  52.  
  53. /* prototypes */
  54.  
  55. void      fatal(char *msg, int status);
  56. char      *concat(char *, char *);
  57. extern      int getswitch(void);
  58. extern      int setswitch(char);
  59.  
  60. main(int argc, char **argv)
  61. {
  62.     char version[] = "eval version 1.01 of "__DATE__ ;
  63.     char usage[] = "Usage: eval command argument argument ...\n";
  64.     static char *command_com = "COMMAND.COM";
  65.     static char dash_c[ 3 ] = { '?', 'c', '\0' };
  66.     int status, i;
  67.     char *shell, *bp, *shellpath, *command;
  68.     char saveswitch;                    /* Save the switch char */
  69.     estring s = {NULL, NULL, 0, 80} ;
  70.  
  71.     if (argc == 1)
  72.         fatal(usage,1);
  73.  
  74.     /* process command line for back-quotes and unexpanded env. vars. */
  75.     rebuild_argv(&argc,&argv);
  76.  
  77.     /* now run the command, with the rest of the line as arguments */
  78.     if (*argv[1] == EXE) {
  79.         /*
  80.          * we can spawn directly, and we know argv is now null terminated,
  81.          * but first we must test the length of the generated command line
  82.          * and truncate it if needed
  83.          */
  84.         int totlen=0;
  85.         for (i=1; argv[i] != NULL; i++) {
  86.             totlen += strlen(argv[i]) + 1;
  87.             if (totlen > MAXARGLINE) {
  88.                 /* we ran over in argv[i] - truncate it and all following args */
  89.                 *(argv[i] + strlen(argv[i]) - (totlen - MAXARGLINE)) = '\0';
  90.                 fputs("Warning: command line too long: truncated\n",stderr);
  91.                 argv[i+1] = (char *)NULL;
  92.                 break;
  93.             }
  94.         }
  95. #ifdef    DEBUG
  96.         fprintf( stderr, "Running: %s", argv[1]+1 );
  97.         for (i=2; argv[i] != NULL; i++) fprintf(stderr," %s",argv[i]);
  98.         fprintf(stderr,"\n");
  99. #endif    DEBUG
  100.         status = spawnvp( P_WAIT, argv[1]+1, argv+1);
  101.     } else {
  102.         /* we need to call a shell */
  103.         /* first make the arguments into one long string */
  104.         for (i=1; argv[i] != NULL; i++) {
  105.             addstring(&s, " ", 1);
  106.             addstring(&s, argv[i], strlen(argv[i]));
  107.         }
  108.         /* Determine the command processor */
  109.         if( ((shell = getenv( "SHELL" ))   == (char *) NULL) &&
  110.             ((shell = getenv( "COMSPEC" )) == (char *) NULL) ) shell = command_com;
  111.         strupr( shell );
  112.         shellpath = shell;
  113.  
  114.         /* Strip off any leading backslash directories */
  115.         shell = strrchr( shellpath, '\\' );
  116.         if ( shell != (char *) NULL )
  117.             ++shell;
  118.         else
  119.             shell = shellpath;
  120.  
  121.         /* Strip off any leading slash directories */
  122.         bp = strrchr( shell, '/'  );
  123.         if ( bp != (char *) NULL )
  124.             shell = ++bp;
  125.         if ( strstr( shell, "KSH" ) != NULL ) {
  126.             /* MKS Shell needs quoted argument */
  127.             command = concat("'",s.b);
  128.             command = concat(command,"'");
  129.         } else {
  130.             command = s.b;
  131.         }
  132.         saveswitch = dash_c[ 0 ] = (char) getswitch();
  133. #ifdef SWITCH
  134.         setswitch('/');
  135.         dash_c[ 0 ] = '/';
  136. #endif
  137.         /* Test the length of the generated command line */
  138.         if (strlen(command) + strlen(shell) + 4 > MAXARGLINE) {
  139.             fputs("Warning: command line too long: truncated\n",stderr);
  140.             *(command + MAXARGLINE -strlen(shell) -strlen(dash_c) -2) = '\0';
  141.         }
  142.         /* Run the program */
  143. #ifdef    DEBUG
  144.         fprintf(stderr,"Running: (%s) %s %s %s\n",shellpath,shell,dash_c,command);
  145. #endif    DEBUG
  146.         status = spawnl( P_WAIT, shellpath, shell, dash_c, command, (char *) NULL );
  147. #ifdef SWITCH
  148.         setswitch(saveswitch);
  149. #endif
  150.     }
  151.     if (status) fprintf(stderr,"eval: %s status %d\n", argv[1], status);
  152.     return(status);
  153. }
  154.  
  155. void fatal(char *msg, int status)
  156. {
  157.     fputs(msg,stderr);
  158.     exit(status);
  159. }
  160.  
  161. char *concat(s1, s2)
  162. char *s1, *s2;
  163. {
  164. /*
  165.  * return the concatenation of s1 and s2 in malloced memory
  166.  */
  167.     char *p;
  168.     p = malloc(strlen(s1)+strlen(s2)+2);
  169.     if (p == (char *)NULL) {
  170.         fatal ("Out of memory\n",1);
  171.     } else {
  172.         strcpy(p,s1);
  173.         strcat(p,s2);
  174.     }
  175.     return(p);
  176. }
  177.